

package com.maoshi.shop.seckill.comment.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.maoshi.shop.bean.app.dto.ShopCartOrderMergerDto;
import com.maoshi.shop.bean.enums.OrderStatus;
import com.maoshi.shop.bean.enums.OrderType;
import com.maoshi.shop.bean.model.Order;
import com.maoshi.shop.bean.model.OrderItem;
import com.maoshi.shop.bean.model.OrderSettlement;
import com.maoshi.shop.bean.model.UserAddrOrder;
import com.maoshi.shop.common.exception.MaoshiShopBindException;
import com.maoshi.shop.common.response.ServerResponse;
import com.maoshi.shop.common.util.Arith;
import com.maoshi.shop.dao.OrderItemMapper;
import com.maoshi.shop.dao.OrderMapper;
import com.maoshi.shop.dao.OrderSettlementMapper;
import com.maoshi.shop.seckill.comment.dao.SeckillMapper;
import com.maoshi.shop.seckill.comment.dao.SeckillSkuMapper;
import com.maoshi.shop.seckill.comment.dto.SeckillOrderMergerDto;
import com.maoshi.shop.seckill.comment.dto.SeckillShopCartItemDto;
import com.maoshi.shop.seckill.comment.model.Seckill;
import com.maoshi.shop.seckill.comment.model.SeckillOrder;
import com.maoshi.shop.seckill.comment.dao.SeckillOrderMapper;
import com.maoshi.shop.seckill.comment.model.SeckillSku;
import com.maoshi.shop.seckill.comment.service.SeckillOrderService;
import com.maoshi.shop.seckill.comment.service.SeckillService;
import com.maoshi.shop.service.UserAddrOrderService;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.Objects;

/**
 * 秒杀订单
 *
 * @author LGH
 * @date 2019-08-28 09:36:59
 */
@Service
@AllArgsConstructor
public class SeckillOrderServiceImpl extends ServiceImpl<SeckillOrderMapper, SeckillOrder> implements SeckillOrderService {

    private final SeckillOrderMapper seckillOrderMapper;

    private final SeckillSkuMapper seckillSkuMapper;

    private final MapperFacade mapperFacade;

    private final Snowflake snowflake;

    private final UserAddrOrderService userAddrOrderService;

    private final OrderSettlementMapper orderSettlementMapper;

    private final OrderItemMapper orderItemMapper;

    private final OrderMapper orderMapper;

    private final SeckillService seckillService;

    private final SeckillMapper seckillMapper;

    @Override
    @CachePut(cacheNames = "ConfirmSeckillOrderCache", key = "#userId")
    public SeckillOrderMergerDto putConfirmOrderCache(String userId, SeckillOrderMergerDto seckillOrderMergerDto) {
        return seckillOrderMergerDto;
    }

    @Override
    @Cacheable(cacheNames = "ConfirmSeckillOrderCache", key = "#userId")
    public SeckillOrderMergerDto getConfirmOrderCache(String userId) {
        return null;
    }

    @Override
    @CacheEvict(cacheNames = "ConfirmSeckillOrderCache", key = "#userId")
    public void removeConfirmOrderCache(String userId) {
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String submit(SeckillOrderMergerDto dto) {

        SeckillShopCartItemDto shopCartItem = dto.getShopCartItem();

        this.checkOrderProdNum(seckillService.getSeckillById(shopCartItem.getSeckillId()),dto.getUserId(),shopCartItem.getProdCount());

        // 更新秒杀sku库存，乐观锁
        if(seckillSkuMapper.updateStocks(shopCartItem.getSeckillSkuId(),shopCartItem.getProdCount()) != 1) {
            throw new MaoshiShopBindException("本商品已被秒杀完毕，下次记得早点来哟");
        }


        Date now = new Date();
        String userId = dto.getUserId();

        Long shopId = shopCartItem.getShopId();
        String orderNumber = String.valueOf(snowflake.nextId());

        // 把订单地址保存到数据库
        UserAddrOrder userAddrOrder = mapperFacade.map(dto.getUserAddr(), UserAddrOrder.class);

        userAddrOrder.setUserId(userId);
        userAddrOrder.setCreateTime(now);


        // 保存订单地址信息
        userAddrOrderService.save(userAddrOrder);

        // 订单地址id
        Long addrOrderId = userAddrOrder.getAddrOrderId();


        OrderItem orderItem = new OrderItem();
        orderItem.setShopId(shopId);
        orderItem.setOrderNumber(orderNumber);
        orderItem.setProdId(shopCartItem.getProdId());
        orderItem.setSkuId(shopCartItem.getSkuId());
        orderItem.setSkuName(shopCartItem.getSkuName());
        orderItem.setProdCount(shopCartItem.getProdCount());
        orderItem.setProdName(shopCartItem.getProdName());
        orderItem.setPic(shopCartItem.getPic());
        orderItem.setPrice(shopCartItem.getPrice());
        orderItem.setUserId(userId);
        orderItem.setProductTotalAmount(shopCartItem.getProductTotalAmount());
        orderItem.setRecTime(now);
        orderItem.setCommSts(0);
        orderItem.setBasketDate(shopCartItem.getBasketDate());
        // 实际订单项支付金额
        orderItem.setActualTotal(shopCartItem.getActualTotal());
        // 分摊优惠金额
        orderItem.setShareReduce(shopCartItem.getShareReduce());
        // 保存订单项
        orderItemMapper.insert(orderItem);

        // 订单信息
        Order order = new Order();

        order.setShopId(shopId);
        order.setOrderNumber(orderNumber);
        // 订单商品名称
        order.setProdName(shopCartItem.getProdName());
        // 用户id
        order.setUserId(userId);
        // 商品总额
        order.setTotal(dto.getTotal());
        // 实际总额
        order.setActualTotal(dto.getActualTotal());
        order.setPlatformAmount(0.0);
        order.setStatus(OrderStatus.UNPAY.value());
        order.setUpdateTime(now);
        order.setCreateTime(now);
        order.setIsPayed(0);
        order.setDeleteStatus(0);
        order.setProductNums(dto.getTotalCount());
        order.setAddrOrderId(addrOrderId);
        order.setReduceAmount(Arith.add(dto.getTransfee(), Arith.sub(dto.getTotal(), dto.getActualTotal())));
        order.setFreightAmount(dto.getTransfee());
        order.setRemarks(dto.getRemarks());
        order.setOrderType(OrderType.SECKILL.value());


        // 保存订单信息
        orderMapper.insert(order);


        // 插入订单结算表
        OrderSettlement orderSettlement = new OrderSettlement();
        orderSettlement.setUserId(userId);
        orderSettlement.setIsClearing(0);
        orderSettlement.setCreateTime(now);
        orderSettlement.setOrderNumber(orderNumber);
        orderSettlement.setPayAmount(order.getActualTotal());
        orderSettlement.setPayStatus(0);
        orderSettlement.setVersion(0);
        orderSettlementMapper.insert(orderSettlement);

        // 保存秒杀订单信息
        SeckillOrder seckillOrder = new SeckillOrder();
        seckillOrder.setCreateTime(new Date());
        seckillOrder.setOrderNumber(orderNumber);
        seckillOrder.setProdCount(shopCartItem.getProdCount());
        seckillOrder.setSeckillId(shopCartItem.getSeckillId());
        seckillOrder.setUserId(dto.getUserId());
        seckillOrder.setProdId(shopCartItem.getProdId());
        seckillOrder.setSeckillSkuId(shopCartItem.getSeckillSkuId());
        // 秒杀成功等待支付
        seckillOrder.setState(0);
        seckillOrderMapper.insert(seckillOrder);

        // 更新活动剩余库存
        if (seckillMapper.updateStocksById(shopCartItem.getSeckillId(), shopCartItem.getProdCount()) < 1) {
            throw new MaoshiShopBindException("本商品已被秒杀完毕，下次记得早点来哟");
        }

        return orderNumber;
    }

    @Override
    public void checkOrderProdNum(Seckill seckill,String userId, int prodCount) {

        // 判断之前秒杀的商品有没有超过限制，-1表示商品不限制秒杀数量
        if (!Objects.equals(seckill.getMaxNum(), -1)) {
            int dbCount = seckillOrderMapper.selectCount(new LambdaQueryWrapper<SeckillOrder>()
                    .eq(SeckillOrder::getSeckillId, seckill.getSeckillId())
                    .eq(SeckillOrder::getProdId, seckill.getProdId())
                    .eq(SeckillOrder::getUserId, userId)
                    .ne(SeckillOrder::getState, -1));
            if (seckill.getMaxNum() < prodCount + dbCount) {
                throw new MaoshiShopBindException("本次秒杀商品限购" + seckill.getMaxNum() + "件");
            }
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelOrderUnpayOrderByTime() {
        Date now = new Date();
        // 还原库存
        seckillSkuMapper.returnStocks(now);
        // 还原库存
        seckillMapper.returnStocks(now);
        // 修改订单状态
        orderMapper.cancelSeckillOrderByTime(now);
        // 将秒杀订单状态改为失效状态
        seckillOrderMapper.cancelUnpayOrder();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelUnpayOrderByOrderNumber(String orderNumber) {
        // 还原秒杀库存
        seckillSkuMapper.returnStocksByOrderNumber(orderNumber);

        // 还原秒杀库存
        seckillMapper.returnStocksByOrderNumber(orderNumber);

        seckillOrderMapper.cancelUnpayOrderByOrderNumber(orderNumber);
    }
}
